package com.xxl.job.executor.service.jobhandler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.mapper.ProductDeferredInfoMapper;
import com.ruoyi.bizsys.mapper.ProductRelationDeferredMapper;
import com.ruoyi.bizsys.service.ILoanIouService;
import com.ruoyi.bizsys.service.ILoanOrderService;
import com.ruoyi.bizsys.service.IProductDeferredInfoService;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.bizsys.vo.MonnifyReservedAccount;
import com.ruoyi.business.domain.CustLoanIou;
import com.ruoyi.business.service.IBatchDateJobService;
import com.ruoyi.business.service.ICreditService;
import com.ruoyi.business.service.ICustVaService;
import com.ruoyi.business.service.ILoanApplyService;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.Func;
import com.ruoyi.system.service.ISysConfigService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.executor.mapper.QuartzSmsMapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 提醒任务
 */
@Slf4j
@Component
@AllArgsConstructor
public class RepaymentReminderJob {

    private ILoanApplyService loanService;

    private ICreditService creditService;

    private QuartzSmsMapper quartzSmsMapper;

    private IBatchDateJobService batchDateJobService;

    private ILoanIouService loanIouService;

    private ICustVaService custVaService;

    private ILoanOrderService orderService;

    private ISysConfigService sysConfigService;

    private ProductRelationDeferredMapper productRelationDeferredMapper;

    private IProductDeferredInfoService productDeferredInfoService;

    private ProductDeferredInfoMapper deferredInfoMapper;

    private static int MAX_SIZE = 1000;

    @XxlJob("repaymentReminderJobHandler")
    public void reminder() {
        XxlJobHelper.log("还款提醒任务 Start >>>>>>>>>>");

        List<SmsTask> smsTasks = new ArrayList<>();
        List<CustLoanIou> custLoanIouList = loanService.getCustNotSettledIou();
        custLoanIouList.stream().forEach(p -> {
            try {
                //查找Monnify虚拟账户
                JSONObject smsJson = new JSONObject();
                smsJson.put("lastName", p.getLastName());
                smsJson.put("contractNo", p.getContractNo());
                //剩余应还
                smsJson.put("RemainingAmt", p.getRepaymentAmt());
                smsJson.put("intervalDays", Math.abs(p.getIntervalDays()));
                //还款账号
                smsJson.put("cardLast4", p.getCardLast4());
                //Monnify虚拟还款账号
                MonnifyReservedAccount monnifyReservedAccounts = custVaService.getVaReservedAccount(p.getCustNo());
                smsJson.put("VAaccountnumber", monnifyReservedAccounts == null ? "" : monnifyReservedAccounts.getAccountNumber());
                smsJson.put("BankName", monnifyReservedAccounts == null ? "" : monnifyReservedAccounts.getBankName());
                smsJson.put("repaymentDate", DateUtils.parseDateToStr(DateUtils.DD_MM_YYYY, DateUtils.dateTime(DateUtils.YYYY_MM_DD_SLASH, p.getRepayDate())));
                smsJson.put("defaultInterest", p.getLoanInterest());
                smsJson.put("preline", p.getPreLine());

                LoanIou loanIou = loanIouService.getOne(new QueryWrapper<LoanIou>().eq("loan_serial_no", p.getLoanSerialNo()).ne("iou_status", LoanIou.LOAN_IOU_STATUS_SETTLE).eq("state", BizConstants.BIZ_STATUS_1));
                ProductInfo productInfo = orderService.selectLoanOrderProduct(p.getCustNo());
                if (productInfo != null) {
                    smsJson.put("credit_rating", sysConfigService.selectConfigKey(productInfo.getCreditRating()));
                    smsJson.put("overdueDay", DateUtils.apartDay(loanIou.getIsDeferred() != null ? loanIou.getDeferredRepayDate() : loanIou.getRepayDate()));
                    smsJson.put("mini_repay_amount", getMinPay(loanIou, productInfo).setScale(2, BigDecimal.ROUND_UP));
                }

                SmsTask smsTask = new SmsTask();
                smsTask.setUserId(p.getUserId());
                smsTask.setCustNo(p.getCustNo());
                smsTask.setCountryCode("+234");
                smsTask.setPhone(p.getPhone());
                smsTask.setNoticeType(BizConstants.SMS_NOTICE_TYPE_REPAYMENT);
                smsTask.setSmsParam(JSON.toJSONString(smsJson));

                //是否已有代扣短信，有则跳过当前短信
                if (quartzSmsMapper.withholdCountOnToday(p.getUserId()) > 0) {
                    return;
                }

                int intervalDays = p.getIntervalDays();
                //正常借贷
                if (p.getIouStatus() == 0) {
                    //14天产品T-7还款提醒 || 14天产品T-5还款提醒 || 7天/14天产品T-3还款提醒
                    String periodNum = p.getPeriodNum();
                    boolean tn = ("14".equals(periodNum) && (intervalDays == 7 || intervalDays == 5 || intervalDays == 3))
                            || ("7".equals(periodNum) && intervalDays == 3);
                    if (tn) {
                        //默认还款提醒
                        smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_N);
                        //T-3 且 测算额度不为空 则 发送提额提醒短信

                        if (intervalDays == 3 && Func.isNotEmpty(p.getPreLine()) && Integer.parseInt(p.getPreLine()) > 0) {
                            smsTask.setNoticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE);
                            smsTask.setSmsType(BizConstants.SMS_TYPE_RAISE_LIMIT_REMIND_T_3);
                        }
                        smsTasks.add(smsTask);
                    }

                    //还款前两天
                    if (intervalDays == 2) {
                        int i = repaymentSms(productInfo, intervalDays, loanIou);
                        if (i == 1) {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_2);
                            smsTasks.add(smsTask);
                        } else {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_1);
                            smsTasks.add(smsTask);
                        }
                    }

                    //还款前一天
                    if (intervalDays == 1) {
                        int i = repaymentSms(productInfo, intervalDays, loanIou);
                        if (i == 1) {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_1);
                            smsTasks.add(smsTask);
                        } else {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_1);
                            smsTasks.add(smsTask);
                        }
                    }

                    //还款日
                    if (intervalDays == 0) {
                        int i = repaymentSms(productInfo, intervalDays, loanIou);
                        if (i == 1) {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_0);
                            smsTasks.add(smsTask);
                        } else {
                            //默认还款提醒
                            smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_0);
                            //T-0 且 测算额度不为空 则 发送提额提醒短信
                            if (Func.isNotEmpty(p.getPreLine()) && Func.isNotEmpty(p.getPreLine()) && Integer.parseInt(p.getPreLine()) > 0) {
                                smsTask.setNoticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE);
                                smsTask.setSmsType(BizConstants.SMS_TYPE_RAISE_LIMIT_REMIND_T_0);
                            }
                            smsTasks.add(smsTask);
                        }
                    }
                }

                //逾期
                if (p.getIouStatus() == 2) {
                    //逾期一天
                    if (intervalDays == -1) {
                        int i = repaymentSms(productInfo, intervalDays, loanIou);
                        if (i == 1) {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_COLL_RPYMT_NTCE_DFR_T_M1);
                            smsTasks.add(smsTask);
                        } else {
                            smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_M1);
                            smsTasks.add(smsTask);
                        }
                    }

                    //逾期3天
                    if (intervalDays == -3) {
                        smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_M3);
                        smsTasks.add(smsTask);
                    }

                    //逾期5天
                    if (intervalDays == -5) {
                        smsTask.setSmsType(BizConstants.SMS_TYPE_REPAYMENT_T_M5);
                        smsTasks.add(smsTask);
                    }
                }

                if (smsTasks.size() >= MAX_SIZE) {
                    batchDateJobService.saveBatchSmsTask(smsTasks);
                    smsTasks.clear();
                }

                Thread.sleep(50);
            } catch (Exception e) {
                log.error("repaymentReminderTask1 异常：userId:{}", p.getUserId(), e);
            }
        });

        creditService.getCreditWithoutLoanList().forEach(p -> {
            try {
                boolean res = Func.isNotEmpty(p.getPreLine()) && p.getPreLine().compareTo(BigDecimal.ZERO) > 0;
                if (!res) {
                    return;
                }
                JSONObject smsJson = new JSONObject();
                smsJson.put("lastName", p.getLastName());
                smsJson.put("preline", p.getPreLine());
                SmsTask smsTask = new SmsTask();
                smsTask.setUserId(p.getUserId());
                smsTask.setCustNo(p.getCustNo());
                smsTask.setCountryCode("+234");
                smsTask.setPhone(p.getPhone());
                smsTask.setNoticeType(BizConstants.SMS_NOTICE_TYPE_NOTICE);
                smsTask.setSmsParam(JSON.toJSONString(smsJson));
                smsTask.setSmsType(BizConstants.SMS_TYPE_RAISE_LIMIT_REMIND_NO_LOAN);

                smsTasks.add(smsTask);
                if (smsTasks.size() >= MAX_SIZE) {
                    batchDateJobService.saveBatchSmsTask(smsTasks);
                    smsTasks.clear();
                }
            } catch (Exception e) {
                log.error("repaymentReminderTask2 异常：userId:{}", p.getUserId(), e);
            }
        });

        if (smsTasks.size() > 0) {
            batchDateJobService.saveBatchSmsTask(smsTasks);
        }

        XxlJobHelper.log("还款提醒任务 End >>>>>>>>>>");
    }

    private int repaymentSms(ProductInfo productInfo, int status, LoanIou loanIou) {
        if (productInfo != null) {
            //满足权益
            switch (status) {
                case 2://还款前两天
                    return 1;
                case 1://还款前一天
                    return 1;
                case 0: //还款当天
                    return 1;
                case -1://逾期
                    BigDecimal principal = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
                    List<ProductDeferredInfo> productDeferredInfoList = deferredInfoMapper.getProductDerferedsForShow(productInfo.getId(), principal, loanIou.getPeriodNum(), productInfo.getDeferredMaxDays());
                    if (productDeferredInfoList.size() > 0 && DateUtils.apartDay(loanIou.getRepayDate()) <= productDeferredInfoList.get(0).getNumDeferredRetainDay()) {
                        return 1;
                    }
                    return 0;
            }
        }
        return 0;
    }


    /**
     * 计算minPay
     *
     * @param loanIou
     * @param
     * @return
     */
    private BigDecimal getMinPay(LoanIou loanIou, ProductInfo productInfo) {
        List<ProductRelationDeferred> productRelationDeferreds = productRelationDeferredMapper.selectCodeById(productInfo.getId());
        ProductDeferredInfo productDeferredInfo = productDeferredInfoService.getOne(new QueryWrapper<ProductDeferredInfo>()
                .eq("id", productRelationDeferreds.get(0).getProductDeferredId())
                .eq("num_deferred_day", "7")
                .last("limit 1")
        );
        BigDecimal toBeRepaid = loanIou.getLoanPrincipal().subtract(loanIou.getRepaidPrincipal());
        BigDecimal deferredInterest = BigDecimal.ZERO;
        BigDecimal deferredServiceFee = BigDecimal.ZERO;
        if (null != productDeferredInfo) {
            deferredInterest = toBeRepaid.multiply(productDeferredInfo.getInterestRate()).multiply(new BigDecimal(productDeferredInfo.getNumDeferredDay()));
            deferredServiceFee = toBeRepaid.multiply(productDeferredInfo.getServiceRate());
        }
        BigDecimal interestAmt = loanIou.getLoanInterest().subtract(loanIou.getRepaidInterest());
        BigDecimal serviceFee = loanIou.getServiceFee().subtract(loanIou.getRepaidServiceFee());
        BigDecimal lateFee = loanIou.getLateFee().subtract(loanIou.getRepaidLateFee()).subtract(loanIou.getFeeRemissionAmt());
        BigDecimal minRepay = interestAmt.add(serviceFee).add(lateFee).add(deferredInterest).add(deferredServiceFee);
        log.info("minRepay:{}", minRepay);
        return minRepay;
    }
}
